/*
 * TimeIncrementEvolutiveStrategy.cpp
 *
 *  Created on: 02/10/2011
 *      Author: godinho
 */

#include <evolutive/TimeIncrementEvolutiveStrategy.h>
#include <evolutive/EvolutiveCaseGenerator.h>
#include <evolutive/EvolutiveCaseGeneratorBuilder.h>
#include <evolutive/RandomCaseGen.h>
#include <evolutive/EventListener.h>
#include <evolutive/output/CasesOutput.h>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>

class MyEventListener : public EventListener {
public:
	MyEventListener(CasesOutput* co) : mOutput(co) {
		co->open();
	}

	~MyEventListener() {
	}

	virtual void newGeneration(int id) {
		mGenerationNum = id;
	}

	virtual void newCase(Case* parent1, Case* parent2, int childNum, Case* child, int crossOver, std::vector<int> mutations) {

	}

	virtual void generation(std::vector<Case*> cases) {
		mOutput->appendGeneration(mGenerationNum, cases);
	}

private:
	CasesOutput* mOutput;
	int mGenerationNum;
};


TimeIncrementEvolutiveStrategy::TimeIncrementEvolutiveStrategy() {
	mEvolutiveAlgorithm = 0;
}

TimeIncrementEvolutiveStrategy::~TimeIncrementEvolutiveStrategy() {
	// TODO Auto-generated destructor stub
}

Case* TimeIncrementEvolutiveStrategy::run(localview::LocalView* lv, int phaseId, int timestep) {

	//TODO case based mechanism
	//Select initial population
	RandomCaseGen randomGen;
	std::vector<Case*> initialPopulation;
	Case* aux;
	for(int i = 0; i < 10; i++) {
		aux = randomGen.generate();
		initialPopulation.push_back(aux);
	}

	//Setup evolutive generator
	EvolutiveCaseGeneratorBuilder builder;

	//Cases output debug - TODO make it conditional
	std::ostringstream casesOutputFile;
	casesOutputFile << "cases_" << lv->getTLSId() << "_" << timestep << "_" << phaseId;

    CasesOutput casesOutput(casesOutputFile.str());
	MyEventListener eventListener(0);
	builder.setEventListener(&eventListener);

	mEvolutiveAlgorithm = builder.buildEvolutiveCaseGenerator();
	mEvolutiveAlgorithm->setLocalview(lv);

	mEvolutiveAlgorithm->startEvolution(initialPopulation);

	casesOutput.close();

	//Select case
	std::vector<Case*> resultCases = mEvolutiveAlgorithm->getCases();

	std::vector<Case*>::iterator casesIt;
	Case* bestCase = (*resultCases.begin());
	for(casesIt = resultCases.begin()+1; casesIt != resultCases.end(); casesIt++) {
		if( (*casesIt)->getFitness() > bestCase->getFitness() ) {
			bestCase = (*casesIt);
		}
	}

	//TODO store cases

	delete mEvolutiveAlgorithm;

	return bestCase;
}

void TimeIncrementEvolutiveStrategy::onStop() {
	if(mEvolutiveAlgorithm != 0) {
		mEvolutiveAlgorithm->setTimedOut();
	}

	//Release case Recycler
	CaseRecycler::releaseRecycler();
}
